home *** CD-ROM | disk | FTP | other *** search
- #include <limits.h>
- #include <string.h>
- #include <new.h>
-
-
- #include "config.h"
-
- #include "arch-specific.h"
- #include "heap.h"
-
- #include "privateheap.h"
- #include "processheap.h"
-
-
- privateHeap::privateHeap (void)
- : _arena (0),
- _arenaRemaining (0)
- {
- for (int i = 0; i < hoardHeap::SIZE_CLASSES; i++) {
- _blocks[i] = 0;
- }
- }
-
-
- // malloc (sz):
- // inputs: the size of the object to be allocated.
- // returns: a pointer to an object of the appropriate size.
-
- void * privateHeap::malloc (const size_t size)
- {
-
- block * b = 0;
- block * leftOver = 0;
- size_t sz = (size == 0) ? 1 : size;
-
- const int sizeclass = sizeClass (sz);
-
- // Determine the actual size of the block.
- size_t actualSize = hoardHeap::sizeFromClass (sizeclass);
- assert (actualSize >= sz);
-
- // Determine the size to allocate (block header + actual size).
- int allocateSize = hoardHeap::align (sizeof(block) + actualSize);
- assert ((allocateSize & hoardHeap::ALIGNMENT_MASK) == 0);
-
- lock();
-
- if (_blocks[sizeclass]) {
- // We had a block on our free list.
- b = _blocks[sizeclass];
- _blocks[sizeclass] = b->getNext();
- } else {
- // We don't have a free block for this size.
- // See if we have memory left in the arena.
- if (_arenaRemaining < allocateSize) {
- // Not enough.
- // Put the remaining arena onto a free list
- // and then make a new one.
- // (If there's enough room left to make a block.)
- if (_arenaRemaining > sizeof(block) + sizeFromClass(0)) {
- leftOver = new (_arena) block (NULL);
- _arenaRemaining -= sizeof(block);
-
- // Put it into the right class (not too big!)
- int leftOverClass = sizeClass (_arenaRemaining);
- while (sizeFromClass (leftOverClass) > _arenaRemaining) {
- leftOverClass--;
- }
-
- assert (sizeFromClass (leftOverClass) <= _arenaRemaining);
-
- leftOver->setActualSize (sizeFromClass (leftOverClass));
- leftOver->markAllocated();
-
- #if HEAP_FRAG_STATS
- leftOver->setRequestedSize (0);
- #endif
- }
- // Make a new arena.
- _arena = (void *) hoardSbrk (MAX (allocateSize, HEAP_REFILL_SIZE));
- _arenaRemaining = MAX (allocateSize, HEAP_REFILL_SIZE);
-
- #if HEAP_FRAG_STATS
- pHeap->setAllocated (0, _arenaRemaining);
- #endif
- if (_arena == (void *) -1) {
- // There is no memory left!
- unlock();
- return 0;
- }
-
- // Align the new arena.
- char * oldarena = (char *) _arena;
- _arena = (char *) hoardHeap::align ((unsigned int) _arena);
- _arenaRemaining = _arenaRemaining - (int) ((char *) _arena - oldarena);
- assert ((((unsigned int) _arena) & hoardHeap::ALIGNMENT_MASK) == 0);
- }
-
- assert (!b);
- assert ((((unsigned int) _arena) & hoardHeap::ALIGNMENT_MASK) == 0);
- assert (_arenaRemaining >= sizeof(block));
-
- // Carve out b from the arena.
- b = new (_arena) block (NULL);
- _arena = (void *) ((char *) _arena + allocateSize);
- _arenaRemaining -= allocateSize;
- }
-
- assert (b);
-
- b->markAllocated();
- b->setActualSize (actualSize);
-
- #if HEAP_FRAG_STATS
- b->setRequestedSize (align(size));
- pHeap->setAllocated (align(size), 0);
- #endif
-
- // Skip past the block header,
- // and return the pointer.
-
- unlock();
- assert (b->isValid());
-
- if (leftOver) {
- free ((void *) (leftOver + 1));
- }
-
- return (void *) (b + 1);
- }
-
-
- // free (ptr, pheap):
- // inputs: a pointer to an object allocated by malloc(), above.
- // side effects: returns the block to the object's superblock;
- // updates the thread heap's statistics;
- // may release the superblock to the process heap.
-
-
- void privateHeap::free (void * ptr)
- {
- if (!ptr) {
- return;
- }
-
- // Find the block corresponding to this ptr.
-
- block * const b = (block *) ptr - 1;
- assert (b->isValid());
- b->markFree();
-
- size_t sz = b->getActualSize();
- #if HEAP_FRAG_STATS
- pHeap->setDeallocated (b->getRequestedSize(), 0);
- #endif
-
- int sizeclass = hoardHeap::sizeClass (sz);
-
- lock();
-
- // Put b into the appropriate freelist.
- b->setNext (_blocks[sizeclass]);
- _blocks[sizeclass] = b;
-
- unlock();
- }
-